using System;
using System.Collections.Generic;
using System.Linq;

namespace ICP_MS.Plugin.HPLC;

public static class FreqAnalyzer
{
	public static double[] Cmp2Mdl(Complex[] input)
	{
		double[] output = new double[input.Length];
		for (int i = 0; i < input.Length; i++)
		{
			if (input[i].Real > 0.0)
			{
				output[i] = input[i].ToModul();
			}
			else
			{
				output[i] = input[i].ToModul();
			}
		}
		return output;
	}

	public static Complex[] FFT(double[] input, bool invert)
	{
		Complex[] output = new Complex[input.Length];
		for (int i = 0; i < input.Length; i++)
		{
			output[i] = new Complex(input[i]);
		}
		return output = FFT(output, invert);
	}

	public static Complex[] FFT(Complex[] input, bool invert)
	{
		if (input.Length == 1)
		{
			return new Complex[1] { input[0] };
		}
		int length = input.Length;
		int half = length / 2;
		Complex[] output = new Complex[length];
		double fac = Math.PI * -2.0 / (double)length;
		if (invert)
		{
			fac = 0.0 - fac;
		}
		Complex[] evens = new Complex[half];
		for (int j = 0; j < half; j++)
		{
			evens[j] = input[2 * j];
		}
		Complex[] evenResult = FFT(evens, invert);
		Complex[] odds = new Complex[half];
		for (int i = 0; i < half; i++)
		{
			odds[i] = input[2 * i + 1];
		}
		Complex[] oddResult = FFT(odds, invert);
		for (int k = 0; k < half; k++)
		{
			double fack = fac * (double)k;
			Complex oddPart = oddResult[k] * new Complex(Math.Cos(fack), Math.Sin(fack));
			output[k] = evenResult[k] + oddPart;
			output[k + half] = evenResult[k] - oddPart;
		}
		return output;
	}

	public static double[] FreqFilter(double[] data, int Nc, Complex[] Hd)
	{
		int N = data.Length;
		Complex[] fData = FFT(data, invert: false);
		for (int j = 0; j < N; j++)
		{
			fData[j] = Hd[j] * fData[j];
		}
		fData = FFT(fData, invert: true);
		data = Cmp2Mdl(fData);
		for (int i = 0; i < N; i++)
		{
			data[i] /= N;
		}
		return data;
	}

	public static double[] FreqFilter(double[] data, int Nc, double[] Hd)
	{
		int N = data.Length;
		Complex[] fData = FFT(data, invert: false);
		List<Complex> fDataList = new List<Complex>();
		List<Complex> tempList = new List<Complex>();
		fDataList = fData.ToList();
		tempList = fDataList.Take(data.Count() / 2).ToList();
		fDataList.RemoveRange(0, data.Count() / 2);
		fDataList.AddRange(tempList);
		fData = fDataList.ToArray();
		for (int j = 0; j < N; j++)
		{
			fData[j].Real = fData[j].Real * Hd[j];
			fData[j].Image = fData[j].Image * Hd[j];
		}
		fData = FFT(fData, invert: true);
		data = Cmp2Mdl(fData);
		for (int i = 0; i < N; i++)
		{
			data[i] /= N;
		}
		return data;
	}
}
